package org.example.controller;


import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.common.usermodel.PictureType;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.example.utils.QRCodeGenerator;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
import org.springframework.web.bind.annotation.RestController;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.util.Units;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

@RestController
public class WordExportController {

    @GetMapping("/export-word")
    public ResponseEntity<Resource> exportWord() throws IOException, InvalidFormatException, WriterException {
        XWPFDocument document = new XWPFDocument();

        // 创建一个段落并添加文字
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();

        run.setText("名称型号：安全帽");

        // 插入图片到段落中
        run.addBreak(); // 换行
        ByteArrayOutputStream os = new ByteArrayOutputStream();

        QRCodeGenerator.generateQRCodeImage("123456789",320,320,"",os);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(os.toByteArray());
        run.addPicture(byteArrayInputStream, Document.PICTURE_TYPE_JPEG,
                "image.png", Units.toEMU(80), Units.toEMU(80)); // 调整尺寸
        run.addBreak(); // 换行
        run.setText("017088454545757521272121");
        run.addBreak(); // 换行
        run.setText("保管地点：舞钢市供电公司");
        run.addBreak(); // 换行
        run.setText("资产归属：国网平顶山舞钢市供电公司");

        // 将文档写入输出流
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        document.write(byteArrayOutputStream);
        document.close();

        byte[] wordArray = byteArrayOutputStream.toByteArray();

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=example.docx");

        return ResponseEntity.ok()
                .headers(headers)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(new ByteArrayResource(wordArray));
    }
    @GetMapping("/exportWord")
    public void exportWord(HttpServletResponse response) throws IOException, InvalidFormatException, WriterException {
        XWPFDocument document = new XWPFDocument();

        // 创建一个段落并添加文字
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();

        run.setText("名称型号：安全帽");

        // 插入图片到段落中
        run.addBreak(); // 换行
        ByteArrayOutputStream os = new ByteArrayOutputStream();

        QRCodeGenerator.generateQRCodeImage("123456789",320,320,"",os);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(os.toByteArray());
        run.addPicture(byteArrayInputStream, Document.PICTURE_TYPE_JPEG,
                "image.png", Units.toEMU(80), Units.toEMU(80)); // 调整尺寸
        run.addBreak(); // 换行
        run.setText("017088454545757521272121");
        run.addBreak(); // 换行
        run.setText("保管地点：舞钢市供电公司");
        run.addBreak(); // 换行
        run.setText("资产归属：国网平顶山舞钢市供电公司");
        response.setContentType("application/octet-stream;charset=ISO8859-1");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("fileName"+".docx", "UTF-8"));
        response.addHeader("Pargam", "no-cache");
        response.addHeader("Cache-Control", "no-cache");
        // 将文档写入输出流
//        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        document.write(response.getOutputStream());

        document.close();

//        byte[] wordArray = byteArrayOutputStream.toByteArray();

//        HttpHeaders headers = new HttpHeaders();
//        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=example.docx");


    }

    @GetMapping("/exportWord1")
    public ResponseEntity<byte[]> exportWord1(HttpServletResponse response) throws Exception {
        // 1. 构造Word文档
        XWPFDocument document = new XWPFDocument();

        // 2. 插入内容（示例数据，实际可从数据库获取）
        List<AssetInfo> assets = Arrays.asList(
                new AssetInfo("01708000000000005418996", "输电运检中心输电带电一班工器具室", "国网商丘供电公司-输电运检中心", "安全带-全身式,z 坠落悬挂"),
                new AssetInfo("017080000000000051297", "汤阴变安全工器具室", "国网安阳供电公司-变电运维中心", "安全带-半身式,z 坠落悬挂"),
                new AssetInfo("01708000000000004846653", "输电运检中心输电检修二班工器具室", "国网商丘供电公司-输电运检中心", "安全带-全身式,z 坠落悬挂"),
                new AssetInfo("017080000000000051303", "汤阴变安全工器具室", "国网安阳供电公司-变电运维中心", "安全带-半身式,z 坠落悬挂")
        );

        // 3. 遍历数据，插入二维码+文字
        for (AssetInfo asset : assets) {
            insertAsset(document, asset);
        }

        // 4. 将Word写入响应流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        document.write(out);
        byte[] content = out.toByteArray();

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=assets.docx");
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);

        return ResponseEntity.ok()
                .headers(headers)
                .body(content);
    }

    private void insertAsset(XWPFDocument document, AssetInfo asset) throws Exception {
        // 3.1 插入二维码（生成图片并嵌入Word）
        String qrContent = asset.getAssetCode(); // 二维码内容（示例为资产编码）
//        byte[] qrImageBytes = generateQRCode(qrContent, 150, 150); // 生成二维码图片字节流
        XWPFParagraph qrParagraph = document.createParagraph();
        XWPFRun qrRun = qrParagraph.createRun();
//        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(qrImageBytes);
//        qrRun.addPicture(byteArrayInputStream, XWPFDocument.PICTURE_TYPE_PNG, "QRCode", Units.toEMU(150), Units.toEMU(150)); // 插入二维码，尺寸150x150像素
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        QRCodeGenerator.generateQRCodeImage(qrContent, 150, 150,"", os);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(os.toByteArray());
        qrRun.addPicture(byteArrayInputStream, XWPFDocument.PICTURE_TYPE_PNG, "QRCode", Units.toEMU(150), Units.toEMU(150)); // 插入二维码，尺寸150x150像素

        qrRun.addBreak(); // 换行

        // 3.2 插入文字信息（分行展示）
        XWPFParagraph textParagraph = document.createParagraph();
        XWPFRun textRun = textParagraph.createRun();
        textRun.setFontSize(12); // 字体大小
        textRun.setText("保管地点：" + asset.getStorageLocation() + "\n" +
                "资产归属：" + asset.getAssetOwner() + "\n" +
                "名称型号：" + asset.getAssetNameModel() + "\n");
        textRun.addBreak(); // 换行，分开每条资产信息
    }

    // 生成二维码（基于ZXing）
    private byte[] generateQRCode(String content, int width, int height) throws Exception {
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, "PNG", out);
        return out.toByteArray();
    }
    // 资产信息实体类
    private static class AssetInfo {
        private final String assetCode;
        private final String storageLocation;
        private final String assetOwner;
        private final String assetNameModel;

        public AssetInfo(String assetCode, String storageLocation, String assetOwner, String assetNameModel) {
            this.assetCode = assetCode;
            this.storageLocation = storageLocation;
            this.assetOwner = assetOwner;
            this.assetNameModel = assetNameModel;
        }

        public String getAssetCode() {
            return assetCode;
        }

        public String getStorageLocation() {
            return storageLocation;
        }

        public String getAssetOwner() {
            return assetOwner;
        }

        public String getAssetNameModel() {
            return assetNameModel;
        }
    }

    public static void main(String[] args) {
        // 创建一个新的XWPFDocument对象
        XWPFDocument document = new XWPFDocument();

        try {
            // 读取图片文件
            FileInputStream is = new FileInputStream("C:\\Users\\zsn\\Pictures\\Saved Pictures\\QRTest.png");

            // 创建一个段落用于放置图片
            XWPFParagraph imageParagraph = document.createParagraph();
            XWPFRun imageRun = imageParagraph.createRun();

            // 设置图片宽度为大约四行文字宽度（这里使用了一个估计值，可能需要根据实际情况调整）
            int imageWidth = 4 * (int) (Units.toEMU(1) * 12); // 假设每个字符平均宽度为12个EMU单位（这是一个估计值）
            // 设置图片高度（这里使用了一个固定值，可以根据需要调整）
            int imageHeight = Units.toEMU(200);

            // 将图片添加到运行中
            imageRun.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, "QRTest", 30, 30);
            is.close();

            // 为图片段落设置一些间距
            imageParagraph.setSpacingAfter(Units.toEMU(20));

            // 创建一个数组存储要在图片右侧显示的文本
            String[] rightTextLines = {
                    "第一行：这是图片右侧的文本。",
                    "第二行：另一行文本在图片旁边。",
                    "第三行：更多文本内容。",
                    "第四行：最后一行在图片旁边的文本。"
            };

            // 遍历数组，为每一行文本创建一个段落
            for (String line : rightTextLines) {
                XWPFParagraph textParagraph = document.createParagraph();
                XWPFRun textRun = textParagraph.createRun();

                // 由于POI不直接支持文本对齐，这里使用空格和制表符（如果有需要的话）来模拟对齐效果
                // 注意：这里使用空格可能不是最精确的方法，但它是一个简单的解决方案
                // 在实际应用中，可能需要更复杂的布局逻辑
                textRun.setText("\t" + line); // 在文本前添加一个制表符（这里只是一个示例，可能需要根据实际情况调整）
                // 如果不需要制表符，可以使用多个空格代替
                // textRun.setText("    " + line); // 使用四个空格作为示例
            }

            // 创建一个新的段落用于放置图片下方的文本
            XWPFParagraph belowImageParagraph = document.createParagraph();
            XWPFRun belowImageRun = belowImageParagraph.createRun();
            belowImageRun.setText("这是图片下方的一行文本。");

            // 将文档写入文件
            try (FileOutputStream out = new FileOutputStream("输出的Word文档.docx")) {
                document.write(out);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                // 关闭文档以释放资源
                document.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static final int TOTAL_WIDTH = 21 * 360000; // 21cm总宽度(EMU)
    private static final int QR_WIDTH = TOTAL_WIDTH / 8;
    private static final int TEXT_WIDTH = TOTAL_WIDTH * 3 / 8;
    private static final int QR_SIZE = (int)(1.52 * 360000); // 1.52cm二维码尺寸
    @GetMapping("/exportWord2")
    public void exportWord2(HttpServletResponse response) throws Exception {
        exportWord3(response);
    }
    public void exportWord3(HttpServletResponse response) throws Exception {
        // 1. 创建文档
        XWPFDocument document = new XWPFDocument();

        // 2. 创建8行4列表格
        XWPFTable table = document.createTable(8, 4);

        // 3. 设置表格总宽度(21cm)
        int totalWidth = 21 * 360000;
        table.setWidth(totalWidth + "");

        // 4. 设置列宽比例(1/8和3/8)
        int qrWidth = totalWidth / 8;
        int textWidth = (totalWidth * 3) / 8;

        // 5. 填充表格内容
        for (int row = 0; row < 8; row++) {
            XWPFTableRow tableRow = table.getRow(row);

            // 设置列宽
            setColumnWidth(tableRow.getCell(0), qrWidth);
            setColumnWidth(tableRow.getCell(1), textWidth);
            setColumnWidth(tableRow.getCell(2), qrWidth);
            setColumnWidth(tableRow.getCell(3), textWidth);


        }
        // 填充内容
        fillTableContent(table);
        // 6. 输出文档
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", "attachment; filename=export.docx");
        document.write(response.getOutputStream());
        document.close();
    }

    private void setColumnWidth(XWPFTableCell cell, int width) {
        CTTblWidth tblWidth = cell.getCTTc().addNewTcPr().addNewTcW();
        tblWidth.setType(STTblWidth.DXA);
        tblWidth.setW(BigInteger.valueOf(width));
    }

    private void fillTableContent(XWPFTable table) throws Exception {
        for (int row = 0; row < 8; row++) {
            // 第1列: 二维码
            insertQRCode(table.getRow(row).getCell(0), "QR_" + row + "_1");

            // 第2列: 4行文字
            insertTextLines(table.getRow(row).getCell(1),
                    "行" + row + "文字1", "行" + row + "文字2",
                    "行" + row + "文字3", "行" + row + "文字4");

            // 第3列: 二维码
            insertQRCode(table.getRow(row).getCell(2), "QR_" + row + "_2");

            // 第4列: 4行文字
            insertTextLines(table.getRow(row).getCell(3),
                    "行" + row + "文字A", "行" + row + "文字B",
                    "行" + row + "文字C", "行" + row + "文字D");
        }
    }

    private void insertQRCode(XWPFTableCell cell, String content) throws Exception {
        cell.removeParagraph(0);
        BufferedImage qrImage = generateQRCode1(content, 200, 200);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(qrImage, "PNG", baos);
        cell.addParagraph().createRun().addPicture(
                new ByteArrayInputStream(baos.toByteArray()),
                Document.PICTURE_TYPE_PNG,
                content,
                QR_SIZE,
                QR_SIZE
        );
    }

    private void insertTextLines(XWPFTableCell cell, String... lines) {
        cell.removeParagraph(0);
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        for (String line : lines) {
            XWPFParagraph p = cell.addParagraph();
            p.setSpacingBetween(11, LineSpacingRule.EXACT);
            XWPFRun r = p.createRun();
            r.setFontFamily("宋体");
            r.setFontSize(11);
            r.setText(line);
        }
    }

    private BufferedImage generateQRCode1(String content, int w, int h) throws WriterException {
        QRCodeWriter writer = new QRCodeWriter();
        BitMatrix matrix = writer.encode(content, BarcodeFormat.QR_CODE, w, h);
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        return image;
    }

}